﻿/**
 * @file ut_string_utils.h
 * @author 贺亚猛
 * @brief 负责封装、维护全部字符串相关算法、操作等
 * @version 0.1
 * @date 2022-01-24
 * @copyright Copyright 2022 Langge Software Co., Ltd. All rights reserved.
 */

#ifndef UT_STRING_UTILS_H
#define UT_STRING_UTILS_H

#include "ut_symbols.h"
#include <string>
#include <vector>
#include <memory>
#include <cwchar>
#include <chrono>

BEGIN_SPACE_LANGE_VDR

/**
 * @brief 字符串实用工具，负责封装字符串相关算法以及操作，
 *        并为外部提供统一操作接口
 */
class UT_API UTStringUtils
{
public:
    /**
     * @brief 格式化字符串
     * @tparam T       变长模板参数
     * @param format   格式化字符串（编码：UTF-8）
     * @param args     格式化参数 
     * @return 返回格式化后的字符串（编码: UTF-8）
     */
    template<typename ...T>
    static std::string FormatString(const std::string &format,T &&...args);
    /**
     * @brief 格式化字符串
     * @tparam T       变长模板参数
     * @param format   格式化字符串（编码：UTF-8）
     * @param args     格式化参数 
     * @return 返回格式化后的字符串（编码：UTF-16）
     */
    template<typename ...T>
    static std::u16string FormatU16string(const std::string &format,T &&...args);
    /**
     * @brief 格式化字符串
     * @tparam T       变长模板参数
     * @param format   格式化字符串（编码：UTF-8）
     * @param args     格式化参数 
     * @return 返回格式化后的字符串（编码：UTF-32）
     */
    template<typename ...T>
    static std::u32string FormatU32string(const std::string &format,T &&...args);
public:
    /**
     * @brief 检测字符串是否以指定字符或字符串开头
     * @param instr        字符串（编码：UTF-8）
     * @param ts           指定字符或字符串（编码：UTF-8）
     * @return true        以指定字符或字符串开头
     * @return false       不以指定字符或字符串开头
     */
    static bool StartsWith(const std::string &instr,const std::string &ts);
    /**
     * @brief 检测字符串是否以指定字符或字符串开头
     * @param instr        字符串（编码：UTF-16）
     * @param ts           指定字符或字符串（编码：UTF-16）
     * @return true        以指定字符或字符串开头
     * @return false       不以指定字符或字符串开头
     */
    static bool StartsWith(const std::u16string &instr,const std::u16string &ts);
    /**
     * @brief 检测字符串是否以指定字符或字符串开头
     * @param instr        字符串（编码：UTF-32）
     * @param ts           指定字符或字符串（编码：UTF-32）
     * @return true        以指定字符或字符串开头
     * @return false       不以指定字符或字符串开头
     */
    static bool StartsWith(const std::u32string &instr,const std::u32string &ts);
    /**
     * @brief 检测字符串是否以指定字符或字符串结尾
     * @param instr  - 字符串（编码：UTF-8）
     * @param ts     - 指定字符或字符串（编码：UTF-8）
     * @return true  - 以指定字符或字符串结尾
     * @return false - 不以指定字符或字符串结尾 
     */
    static bool EndsWith(const std::string &instr,const std::string &ts);
    /**
     * @brief 检测字符串是否以指定字符或字符串结尾
     * @param instr  - 字符串（编码：UTF-16）
     * @param ts     - 指定字符或字符串（编码：UTF-16）
     * @return true  - 以指定字符或字符串结尾
     * @return false - 不以指定字符或字符串结尾 
     */
    static bool EndsWith(const std::u16string &instr,const std::u16string &ts);
    /**
     * @brief 检测字符串是否以指定字符或字符串结尾
     * @param instr  - 字符串（编码：UTF-32）
     * @param ts     - 指定字符或字符串（编码：UTF-32）
     * @return true  - 以指定字符或字符串结尾
     * @return false - 不以指定字符或字符串结尾 
     */
    static bool EndsWith(const std::u32string &instr,const std::u32string &ts);
    /**
     * @brief   用指定子串分割字符串
     * @param      in   输入字符串（编码：UTF-8）
     * @param   delim   指定子串（编码：UTF-8）
     * @return  返回分割后的结果
     */

    static void SplitString(const std::string &in,const std::string &delim,std::vector<std::string>& res);

    static void SplitChars(char* input, const char &delim, std::vector<uint32_t> &res);

    static std::vector<std::string> SpliteString(const std::string &in,const std::string &delim);
    /**
     * @brief   用指定子串分割字符串
     * @param      in   输入字符串（编码：UTF-16）
     * @param   delim   指定子串（编码：UTF-16）
     * @return  返回分割后的结果
     */
    static std::vector<std::u16string> SpliteString(const std::u16string &in,const std::u16string &delim);
    /**
     * @brief   用指定子串分割字符串
     * @param      in   输入字符串（编码：UTF-32）
     * @param   delim   指定子串（编码：UTF-32）
     * @return  返回分割后的结果
     */
    static std::vector<std::u32string> SpliteString(const std::u32string &in,const std::u32string &delim);

    static std::string TimestampFormat(int64_t ts);
public:
    /**
     * @brief 将输入字符串转为UTF-8编码格式
     * @param str    输入字符串（编码：UTF-16）
     * @return 返回转换后的字符串
     */
    static std::string ToUtf8(const std::u16string &str);
    /**
     * @brief 将输入字符串转为UTF-8编码格式
     * @param str    输入字符串（编码：UTF-32）
     * @return 返回转换后的字符串 
     */
    static std::string ToUtf8(const std::u32string &str);
    /**
     * @brief 将输入字符串转为UTF-16编码格式
     * @param str    输入字符串（编码：UTF-8）
     * @return 返回转换后的字符串
     */
    static std::u16string ToUtf16(const std::string &str);
    /**
     * @brief 将字符串转为UTF-16编码格式
     * @param str    输入字符串（编码：UTF-32）
     * @return 返回转换后的字符串
     */
    static std::u16string ToUtf16(const std::u32string &str);
    /**
     * @brief 将输入字符串转为UTF-32编码格式
     * @param str    输入字符串（编码：UTF-8）
     * @return 返回转换后的字符串
     */
    static std::u32string ToUtf32(const std::string &str);
    /**
     * @brief 将输入字符串转为UTF-32编码格式
     * @param str    输入字符串（编码：UTF-16）
     * @return 返回转换后的字符串
     */
    static std::u32string ToUtf32(const std::u16string &str);

    /**
     * @brief 字符串转hex
     * 
     * @param data 
     * @return std::string 
     */
    static std::string StringToHex(const std::string& data);

    static char* rtrim(char* str);
    /**
     * @brief hex转字符串
     * 
     * @param str 
     * @return std::string 
     */
    static std::string HexToStr(const std::string& str);
    static uint64_t Utf16ToWstring(const uint16_t * swc, wchar_t * wcs, const uint64_t& len);

    static void WstringToUtf16(const wchar_t * wcs, uint16_t * swc, uint64_t len);
    static std::wstring utf8ToWstring(const char * cstr);
    static std::string wstringToUtf8(const wchar_t * wcstr);
private:
    UTStringUtils()=delete;
    UTStringUtils(UTStringUtils &&)=delete;
    UTStringUtils(const UTStringUtils &)=delete;
    UTStringUtils &operator=(UTStringUtils &&)=delete;
    UTStringUtils &operator=(const UTStringUtils &)=delete;


};

/**
 * @brief 格式化字符串
 * @tparam T       变长模板参数
 * @param format   格式化字符串（编码： UTF-8）
 * @param args     格式化参数 
 * @return 返回格式化后的字符串
 */
template<typename ...T>
std::string UTStringUtils::FormatString(const std::string &format,T &&...args)
{
    if (format.empty())
    {
        return std::string();
    }

    if(0==sizeof...(args))
    {
        return std::string(format);
    }
    
    const size_t size_buf=1+std::snprintf(nullptr,0,format.c_str(),std::forward<T>(args)...);
    std::unique_ptr<char[]> buf(new(std::nothrow) char[size_buf]);
    if(!buf)
    {
        return std::string("");
    }
    std::snprintf(buf.get(),size_buf,format.c_str(),args...);
    return std::string(buf.get(),buf.get()+size_buf-1);
}

/**
 * @brief 格式化字符串
 * @tparam T       变长模板参数
 * @param format   格式化字符串（编码：UTF-8）
 * @param args     格式化参数 
 * @return 返回格式化后的字符串（编码：UTF-16）
 */
template<typename ...T>
std::u16string UTStringUtils::FormatU16string(const std::string &format,T &&...args)
{
    std::string ret=FormatString(format,std::forward<T>(format)...);
    return ToUtf16(ret);
}

/**
 * @brief 格式化字符串
 * @tparam T       变长模板参数
 * @param format   格式化字符串（编码：UTF-8）
 * @param args     格式化参数 
 * @return 返回格式化后的字符串（编码：UTF-32）
 */
template<typename ...T>
std::u32string UTStringUtils::FormatU32string(const std::string &format,T &&...args)
{
    std::string ret=FormatString(format,std::forward<T>(args)...);
    return ToUtf32(ret);
}

END_SPACE_LANGE_VDR

#endif // !UT_STRING_UTILS_H
